/****************************************************************
 ****************************************************************
 ** JS-Swarming!
 **
 ** A very simple implementation of swarming behavior in pure
 ** Javascript and SVG.
 **
 ** Features:
 ** - Basic biods.
 ** - Attractive/repulsive "emitters".
 ** - Predators!
 ** - Some real-time user interaction.
 **
 **
 ** Written by: Stephen Smithbower [smithy.s@gmail.com]
 ** Written on: September 25th, 2013.
 **
 ** Use as you wish!
 **
 **
 ** CONTROLS:
 ** --------------------------------------------------------------
 ** r		Resets the simulation
 ** k 		Adds an attractive emitter of a random size and strength at the current mouse position.
 **	l 		Adds a repulsive emitter of a random size and strength at the current mouse position.
 ** p 		Adds a new predator at a random position.
 ** b 		Adds a new biod at the current mouse position.
 **
 ** Left Mouse Down 			Pull the biods towards the mouse cursor.
 ** Left Mouse Down + Shift 	Push the biods away from the mouse cursor.
 **
 *****************************************************************
 *****************************************************************/

//////////////////////////////////////////
// GLOBAL VARIABLES						//
//////////////////////////////////////////
import { Vector } from "./Vector.js";
import { Biod } from "./Biod.js";
import { Flock } from "./Flock.js";
import { Emitter } from "./Emitter.js";

var g_simulationInterval = null;
var t_delta = null;
var t_lastFrame = 0;

var g_flock = null;

var g_mouseEmitter = null;
var g_mouseIsDown = false;

var g_keysDown = {}; //Stores all current keypresses.

var g_svg = null;

var g_mouseVec = new Vector(0, 0);

/**
 * Sets up the svg environment and hooks in mouse event listeners.
 * Also kicks off the simulation, which runs at a fixed timestep of
 * one step per 50ms.
 */
function Init() {
    //Init stuff.
    g_svg = document.getElementsByTagName("svg")[0];

    g_svg.addEventListener("mousedown", runFromTheMouse);
    g_svg.addEventListener("mouseup", stopRunFromTheMouse);
    g_svg.addEventListener("mousemove", updateRunningFromTheMouse);

    resetSim();

    //Start the simulation.
    g_simulationInterval = setInterval(runSimulation, 50); //Why 20? Less CPU, is fast enough for bullets to track properly.
}

/**
 * Resets the simulation state.
 */
function resetSim() {
    //If a sim is already running, make sure to remove all svg elements.
    if (g_flock != null) g_flock.die();

    g_flock = new Flock(g_svg);

    //Create a bunch of biods!
    var numBiods = 50;
    var size = 7;
    var prox = 40;
    var speed = 3;
    var turnSpeed = 10;
    var sightRadius = 200;
    var claus = 20;

    var sandboxDims = new Vector(800, 600);

    for (var i = 0; i < numBiods; i++) {
        //position, speed, turnSpeed, radius, proximityRadius, sightRadius, claustrophobicSeverity, sandboxDimensions
        var newBiod = new Biod(
            new Vector(
                BoundedRandom(0, sandboxDims.x),
                BoundedRandom(0, sandboxDims.y)
            ),
            speed,
            turnSpeed,
            size,
            prox,
            sightRadius,
            claus,
            sandboxDims
        );

        //Add the biod to the flock.
        g_flock.addBiod(newBiod);
    }
}

/**
 * Updates the simulation (one step).
 */
function runSimulation() {
    //Update the flock.
    g_flock.update();
}

/**
 * Generates a random number between a min and max value.
 */
function BoundedRandom(min, max) {
    return Math.random() * (max - min) + min;
}

function runFromTheMouse(event) {
    g_mouseIsDown = true;

    g_mouseEmitter = new Emitter(
        new Vector(event.x, event.y),
        4000,
        200,
        "linear",
        true
    );
}

function stopRunFromTheMouse(event) {
    g_mouseIsDown = false;
}

function updateRunningFromTheMouse(event) {
    if (g_mouseIsDown) g_mouseEmitter.position = new Vector(event.x, event.y);

    g_mouseVec = new Vector(event.x, event.y);
}

/**
 * Manages tracking all keydown events (key presses).
 */
addEventListener(
    "keydown",
    function (e) {
        g_keysDown[e.keyCode] = true;
        g_flock.update(g_keysDown);
    },
    false
);

/**
 * Cancels all keypresses (keyup events).
 */
addEventListener(
    "keyup",
    function (e) {
        delete g_keysDown[e.keyCode];
    },
    false
);
Init();
